/*
*  SkySoundEngine.h
*  
*
*  Created by Alexander Trutchenko on 11/02/12.
*  Copyright 2012 Free Team. All rights reserved.
*
*/

#ifndef __Sky_SoundEngine_h__
#define __Sky_SoundEngine_h__

#include "SkyOpenALInclude.h"

#include "stdlib.h"

#include <string>
#include <list>
#include <map>
#include <set>

namespace sky {

// TODO: Single error politics

// TODO: Naming
 
////////////////////////////////////////////////////////
//
/** SkySoundEngine
*  
*/
////////////////////////////////////////////////////////

class SkyOpenALContext;
class SkyBufferManager;

class SkySoundEngine
{
typedef std::list<SkyOpenALContext*> Contexts;
typedef std::map<std::string, int> IDsForKey;
typedef std::set<std::string> Keys;
	
private:
//Contexts
	Contexts _contexts;
	SkyOpenALContext* _currentContext;
	SkyBufferManager* _bufferManager;

	//OpenAL version
	int _magorVersion;
	int _minorVersion;

	//global buffers
	Keys _buffers;
	Keys _compressedFiles;

	ALCdevice*	_outputDevice; // current OpenAL output device 

private:
    static SkySoundEngine* _instance;


private:
    SkySoundEngine();
    ~SkySoundEngine();

public:
	static SkySoundEngine* sharedEngine();
    static void pvt_remove();

public:
//work with output devices
	bool openOutputDevice(const ALCchar *deviceSpecifier); //NULL - open default device 
	bool isOutputDeviceOpened() const { return (_outputDevice != NULL); }
	bool closeOutputdevice();
	void availableOutputDevices(std::list<std::string>& deviceList);
	

//work with contexts
	bool addContext(SkyOpenALContext* context);
	bool removeContext(SkyOpenALContext* context);
	void setCurrentContext(SkyOpenALContext* context);
	inline SkyOpenALContext* currentContext() const { return _currentContext; }
	
//Timer
	void update(float dt);

//Work with context-independent data
		/* Preload compressed files */
	bool preloadCompressedFile(const char* file);
		/* Unload compressed files */
	void unloadCompressedFile(const char* file);
		/* Preload and uncompress(decode with decoders) file and move to OpenAL buffer */ 
	bool preloadFileToBuffer(const char* file);
		/* Free OpenAL buffer from the file */
	void unloadFileFromBuffer(const char* file);

//Global settings
	const char* stringInfo(ALenum infoType); // infoType is AL_VENDOR, AL_VERSION, AL_RENDERER, AL_EXTENSIONS

// Support alc functions

//TODO: refactor this functions
	bool alcIsExtensionAvailable_output(const char *extName) const;
	void* alcFunctionEntryAddress_output(const char *funcName) const;
	ALCenum alcLastError_output() const;
	ALCenum alcEnumValue_output(const char* enumName) const;
	const char* alcStringValue_output(ALCenum token) const;
	int alcIntegerValue_output(ALCenum token) const; //Only for ALC_CAPTURE_SAMPLES, ALC_MAJOR_VERSION, ALC_MINOR_VERSION; current contest setting see in context class

private:
	void clearAllContexts();

}; //class SkySoundEngine

} // namespace sky

#endif //__Sky_SoundEngine_h__
